/**
 * 
 */
package com.p2p.front.tender;

import java.util.List;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;

import com.p2p.base.exception.BizException;
import com.p2p.base.model.Money;
import com.p2p.front.async.AsyncBiz;
import com.p2p.front.dal.model.LoanInfo;
import com.p2p.front.dal.model.LoanVariation;
import com.p2p.front.dal.model.Tender;
import com.p2p.front.result.UserTenderResult;
import com.p2p.front.service.LoanInfoService;
import com.p2p.front.service.LoanRepayService;
import com.p2p.front.service.LoanVariationService;
import com.p2p.front.service.TenderReturnService;
import com.p2p.front.service.TenderService;
import com.p2p.front.service.UserService;
import com.p2p.front.util.RateUtil;
import com.p2p.trans.client.facade.AccountQueryFacade;
import com.p2p.trans.client.facade.AccountTransFacade;
import com.p2p.trans.client.model.AccountVO;
import com.p2p.trans.client.result.AccountQueryResult;
import com.p2p.user.facade.UserQueryFacade;

/**
 * @author ruiqi
 *
 */
public abstract class AbstractTenderBiz {
	protected final Logger logger = LoggerFactory.getLogger(AbstractTenderBiz.class);
	
	@Resource
	protected LoanVariationService loanVariationService;
	
	@Resource
	protected LoanInfoService loanInfoService;
	
	@Resource
	protected AccountTransFacade remoteAccountTransFacade;
	
	@Resource
	protected AccountQueryFacade remoteAccountQueryFacade;
	
	@Resource
	protected UserQueryFacade userQueryFacade;
	
	@Resource
	protected UserService userService;
	
	@Resource
	protected TenderService tenderService;
	
	@Resource
	protected AsyncBiz asyncBiz;
	
	@Resource
	protected LoanRepayService loanRepayService;
	
	@Resource
	protected TenderReturnService tenderReturnService;
	
	
	@Transactional
	public UserTenderResult doBizTransaction(Tender tender){
		UserTenderResult result;
		preTenderProcessing(tender);
        result = tenderProcessing(tender);
        postTenderProcessing(result, tender);
        afterTenderProcessing(tender);
        return result;
	}
	
	protected void preTenderProcessing(Tender tender){
		
	}
	
	protected UserTenderResult tenderProcessing(Tender tender){
		
		UserTenderResult result = new UserTenderResult();
		Long lid = tender.getLid();
		Money amount = tender.getAmount();
		
		//事务锁住抢标状态
		LoanVariation loanVariation = loanVariationService.getAndLockById(lid,null);
		if(loanVariation==null){
			throw new BizException(UserTenderResult.ResultCodeEnum.tender_status_error.name());
			//return result;
		}
		if(loanVariation.getStatus()!=21){
			/*if(loanVariation.getStatus()==12){
				
			}else{
				
			}*/
			throw new BizException(UserTenderResult.ResultCodeEnum.tender_status_error.name());
		}
		//累计投标金额
		Money tenderAmount = loanVariation.addTenderAmount(tender);
		if(tenderAmount.getCent()==0L){
			throw new BizException(UserTenderResult.ResultCodeEnum.tender_allready_full.name());
			
		}
		
		//更新数据库
		boolean updateResult = loanVariationService.update(loanVariation);
		if(!updateResult){
			throw new BizException(UserTenderResult.ResultCodeEnum.tender_common_error.name());
			
		}
		/*if(tenderAmount.getCent()!=amount.getCent()){
			long temp = tender.getRepayAmount().getCent()*tenderAmount.getCent()/amount.getCent();
			tender.setAmount(tenderAmount);
			tender.setRepayAmount(new Money(temp));
		}*/
		
		tenderService.save(tender);
		
		doUserTrans(tender.getUserAccount(),tenderAmount,String.valueOf(tender.getTid()));
		//投标成功返回金额
		result.setSuccess(true);
		result.setTenderAmount(tenderAmount);
		if(loanVariation.getCanTenderAmount().getCent()==0l){
			result.setTenderFull(true);
		}
		return result;
	}
	
	
	protected void postTenderProcessing(UserTenderResult result,Tender tender){
	
	}
	
	protected void afterTenderProcessing(Tender tender){
		
	}
	
	protected abstract void doUserTrans(String accountNo,Money amount,String bizNo);
	
	public void checkTenderPrepare(Tender tender) throws BizException{
		String accountNo = tender.getUserAccount();
		Money tenderAmount = tender.getAmount();
		AccountVO accountVO = getAccountVO(accountNo);
		if(accountVO==null){
			throw new BizException(UserTenderResult.ResultCodeEnum.tender_account_exist.name());
		}
		Money canUserBalance = accountVO.getCanUserBalance();
		if(canUserBalance.getCent()<tenderAmount.getCent()){
			throw new BizException(UserTenderResult.ResultCodeEnum.tender_balance_enough.name());
		}
		
	}
	
	private AccountVO getAccountVO(String accountNo){
		AccountQueryResult queryResult = remoteAccountQueryFacade.getAccountInfo(accountNo);
		if(queryResult.isSuccess()){
			AccountVO accountVO = queryResult.getAccountVO();
			return accountVO;
		}
		return null;
	}
	
	
	@Async
	public void doTenderFullBiz(Long loanId){
		
		LoanInfo loanInfo = loanInfoService.getLoanInfoById(loanId);
		
		boolean bool= loanVariationService.updateStatusForTenderFull(loanId,loanInfo);
		if(!bool){
			return;
		}
		LoanVariation loanStatus = loanVariationService.getByLoanId(loanId);
		if(loanStatus.getStatus()!=32){
			return;
		}
		
		Money totalTenderAmount = loanStatus.getTenderAmount();
		List<Tender> tenderList = tenderService.findSuccesedByLoanId(loanId);
		Money checkTotalAmount = new Money();
		for(Tender tender:tenderList){
			checkTotalAmount.add(tender.getAmount());
		}
		if(checkTotalAmount.getCent()!=totalTenderAmount.getCent()){
			//TODO 金额不一致，通常是程序漏洞
		}
		
		
		doExtraTenderFullBiz(tenderList,loanInfo);
		doExtraLoanFullBiz(loanStatus,loanInfo);

	}
	
	public void doTenderExpiredBiz(Long loanId){
		LoanVariation loanStatus = loanVariationService.getByLoanId(loanId);
		doTenderExpiredBiz(loanStatus);
	}
	
	@Transactional
	public abstract void doTenderExpiredBiz(LoanVariation LoanVariation);
	
	protected void doExtraTenderFullBiz(List<Tender> tenderList,LoanInfo loanInfo){
		
	}
	
	protected abstract void doExtraLoanFullBiz(LoanVariation loanStatus,LoanInfo loanInfo);
	
	
	public abstract void doLoanMoney(LoanVariation loanStatus,LoanInfo loanInfo);

	public void doCreatLoanRepay(LoanVariation loanStatus,LoanInfo loanInfo){
		
		Money allInterest = RateUtil.getAllInterest(loanInfo.getApr(),
				loanInfo.getDeadline(), loanStatus.getTenderAmount(), loanInfo.getRepayMethod());
		boolean bool = loanVariationService.updateStatusForRepay(loanStatus.getLoanId(),allInterest);
		if(!bool){
			logger.error("更新放款状态失败:loanId="+loanInfo.getLid());
		}
		this.loanRepayService.create(loanInfo, loanStatus);
	}
}
